#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdarg.h>
#include <dataset.h>
#include <expression.h>

#define EXP_TO_OPR_CHAR(o) \
	((o) == EXP_OPR_PARENTHESIS_OPEN ? '('  : \
	(o) == EXP_OPR_EQUALS ? '=' : \
	(o) == EXP_OPR_START_WITH ? '[' : \
	(o) == EXP_OPR_CONTAINS ? '*' : \
	(o) == EXP_OPR_END_WITH ? ']' : \
	(o) == EXP_OPR_AND ? '&' : \
	(o) == EXP_OPR_OR ? '|' : \
	(o) == EXP_OPR_NOT ? '!' : \
	(o) == EXP_OPR_PARENTHESIS_CLOSE ? ')' : \
	'?')

void display_indent(int depth, const char *str, ...) {
	int i = 0;
	va_list p;
	va_start(p, str);
	for (i = 0; i < depth; i++) {
		putchar('\t');
	}
	vprintf(str, p);
	va_end(p);
}

void display_exp(Expression *exp, int depth) {
	Expression *param;

	if (exp == NULL)
	{
		printf("!!!!!!!!! exp == NULL !!!!!!!!!!!\n");
		return;
	}

	switch(exp->type) {
	case EXP_IDENTITY:
		display_indent(depth, "IDENT %s\n", exp->exp.ident);
		break;
	case EXP_CONSTANT:
		display_indent(depth, "CONST %s\n", exp->exp.constant);
		break;
	case EXP_UNARY:
		display_indent(depth, "! \\\n");
		display_exp(exp->exp.unary.a, depth + 1);
		break;
	case EXP_BIGRAM:
		display_exp(exp->exp.bigram.a, depth + 1);
		display_indent(depth, "%c <\n", EXP_TO_OPR_CHAR(exp->exp.bigram.opr));
		display_exp(exp->exp.bigram.b, depth + 1);
		break;
	case EXP_FUNCTION:
		display_indent(depth, "func %s (\n", exp->exp.func.name);
		move_head(exp->exp.func.parameters);
		while ((param = (Expression *) next(exp->exp.func.parameters)) != NULL) {
			display_exp(param, depth + 1);
		}
		display_indent(depth, ")\n");
		break;
	default:
		display_indent(depth, "## Unknown Exp %d!\n", exp->type);
		break;
	}
}

void test_parse_token(const char * p) {
	Expression *exp;
	exp_parse(&exp, p, ':');

	display_exp(exp, 0);
}

int main() {
	test_parse_token("a=\"hello\"&(c[\"hi\"|d]\"hello\")&s=200&e*\"ok\":after}");
	test_parse_token("a=\"hello\"&(c[\"hi\"|d]\"hello\")&s=200|P(load)|lon(\"abc\",k)&e*\"ok\":after}");
	test_parse_token("a=\"hello\"&!(c[\"hi\"|d]\"hello\")&s=200|P(load)|lon(\"abc\",k)&e*\"ok\":after}");
	test_parse_token("a=\"hello\"&!(c[\"hi\"|d]\"hello\")&s=200|P(load)|lon(\"abc\",k)&e*\"ok\"|now():after}");
	return 0;
}
